#include "dev_server.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "qt_server.h"
#include "myds.h"
#include "msg_pack.h"
#include "my_hashmap.h"

extern hashmap_t *map;
static int epfd;
static int serverfd;
int waitUeserResp=1;

bool handleHeart(msg_pack_t *pack, int devfd)
{
    // 获取devid
    char devid[20] = {0};
    memcpy(devid, pack_getField(pack, 0)->content, pack_getField(pack, 0)->filedLen);
    // 更新
    data_t *data = hashmap_get(map, devid);
    if (data == NULL || data->devfd <= 0)
    { // 之前没有
        data_t data;
        memcpy(data.devid, devid, 20);
        data.devfd = devfd;
        data.userfd = -1;
        hashmap_put(map, devid, data);
    }
    else
    { // 更新下
        data->devfd = devfd;
    }
    printf("[%s]收到设备[%s]的心跳, devfd=[%d]\n", __func__, devid, devfd);
    hashmap_printself(map);
    // 释放资源
    pack_destroy(pack);
    return true;
}

bool handleVideo(msg_pack_t *pack, int devfd)
{ // 来了来了，最关键的一个接口!!!

    // 获取devid
    char devid[20] = {0};
    int total, packno;
    memcpy(devid, pack_getField(pack, 0)->content, pack_getField(pack, 0)->filedLen);
    memcpy(&total, pack_getField(pack, 1)->content, pack_getField(pack, 1)->filedLen);
    memcpy(&packno, pack_getField(pack, 2)->content, pack_getField(pack, 2)->filedLen);
    printf("[%s]收到设备[%s]的视频数据报文, devfd=[%d],totalLen=[%d],total=[%d],packno=[%d]\n", __func__,
           devid, devfd, pack->totalLen, total, packno);
    //计算crc
    unsigned int crc=0;
    for(int i=0;i<100;i++){
        printf("%02X ", (unsigned char)pack_getField(pack, 3)->content[i]);
        crc+=(unsigned char)pack_getField(pack, 3)->content[i];
    }
    printf("\ncrc=[%ud]\n", crc);

    // 数据转发
    hashmap_printself(map);
    printf("devid=[%s], hashcode=[%d]\n", devid, hashmap_hashcode(devid));
    data_t *data = hashmap_get(map, devid);
    if (data == NULL || data->userfd <= 0)
    {
        printf("hashmap has no data! (data==NULL)=[%d]\n",
               (data == NULL));
        printf("hashmap has no data! (data==NULL)=[%d],(data->userfd <=0)=[%d],data->userfd=[%d]\n",
               (data == NULL), (data->userfd <= 0), data->userfd);
        return false; // do nothing
    }
    int userfd = data->userfd;
    // 直接转发
    char buf[2000];
    pack_2_buf(pack, buf);
    waitUeserResp = 0;
    ssize_t cnt = send(userfd, buf, pack->totalLen, 0);
    printf("[%s]视频流数据: 已经向客户端转发, userfd=[%d], cnt=[%ld]\n", __func__, userfd, cnt);
    // 等待客户端回复
    while(waitUeserResp!=1){};

    // 向设备的回复报文
    msg_pack_t *retPack = pack_create(PACK_DEV_VEDIO_RET);
    pack_add_field(retPack, 4, (char *)&packno);
    char retBuf[20];
    pack_2_buf(retPack, retBuf);
    send(devfd, retBuf, retPack->totalLen, 0);
    free(retPack);

    free(pack);
    return true;
}

static bool recvHandle(int devfd)
{
    // printf("开始进行pack_from_socket\n");
    msg_pack_t *pack = pack_from_socket(devfd);
    // printf("pack_from_socket:::完成!\n");
    if (pack == NULL)
    {
        printf("pack is null!!!\n");
        return false;
    }
    // 根据不同的报文类型，处理报文
    switch (pack->type)
    {
    case PACK_DEV_VEDIO:
        return handleVideo(pack, devfd);
    case PACK_DEV_HEART:
        return handleHeart(pack, devfd);
    default:
        break;
    }

    return true;
}

static void *dev_server_task(void *args)
{
    while (1)
    {
        struct epoll_event events[50];
        int len = epoll_wait(epfd, events, 50, -1);
        for (int i = 0; i < len; i++)
        {
            struct epoll_event e = events[i];
            int fd = e.data.fd;
            if (fd == serverfd)
            { // 新的tcp连接
                struct sockaddr_in addr;
                int addrlen;
                int devfd = accept(serverfd, (struct sockaddr *)&addr, &addrlen);
                struct epoll_event event = {.events = EPOLLIN, .data.fd = devfd};
                epoll_ctl(epfd, EPOLL_CTL_ADD, devfd, &event);
                printf("[%s]有新的客户端连接 clientfd=[%d]\n", __func__, devfd);
            }
            else
            { // 客户端消息
                printf("[%s]收到来自客户端[%d]的消息\n", __func__, fd);
                if (!recvHandle(fd))
                {
                    printf("[%s]断开连接，客户端fd=[%d]\n", __func__, fd);
                    close(fd);
                    epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
                }
            }
        }
    }
}

bool dev_server_init(const char *hostname, const int port)
{
    serverfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("[%s] socket: serverfd=[%d]\n", __func__, serverfd);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(hostname);
    if (bind(serverfd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
    {
        printf("[%s]端口bind失败\n", __func__);
        return false;
    }
    //
    if (listen(serverfd, 50) != 0)
    {
        printf("[%s]listen失败\n", __func__);
        return false;
    }
    //
    epfd = epoll_create(50);
    printf("[%s] epoll_create: epfd=[%d], server=[%d]\n", __func__, epfd, serverfd);
    struct epoll_event event = {.events = EPOLLIN, .data.fd = serverfd};
    epoll_ctl(epfd, EPOLL_CTL_ADD, serverfd, &event);
    //
    pthread_t tid;
    pthread_create(&tid, NULL, dev_server_task, NULL);
    pthread_detach(tid);
    //
    return true;
}